import _ from 'lodash'

export class TaskScheduler {
  constructor() {
    this.tasks = new Map()
    this.timers = new Map()
  }
  
  registerTask(name, config, handler) {
    if (!handler && typeof config === 'function') {
      handler = config
      config = {}
    }
    
    if (!handler && config.handler) {
      handler = config.handler
    }
    
    const { cron, runOnInit = false } = config
    
    const task = {
      name,
      cron,
      handler,
      config,
      stats: {
        runs: 0,
        success: 0,
        failed: 0,
        lastRun: null,
        nextRun: null,
        lastError: null
      }
    }
    
    this.tasks.set(name, task)
    
    const interval = this.parseCron(cron)
    if (interval) {
      const timer = setInterval(() => this.runTask(name), interval)
      this.timers.set(name, timer)
      task.stats.nextRun = Date.now() + interval
    }
    
    if (runOnInit) {
      this.runTask(name)
    }
  }
  
  parseCron(cron) {
    if (!cron) return null
    
    const parts = cron.split(' ')
    
    if (parts[0].startsWith('*/')) {
      const seconds = parseInt(parts[0].substr(2))
      return seconds * 1000
    }
    
    if (parts.length > 1 && parts[1].startsWith('*/')) {
      const minutes = parseInt(parts[1].substr(2))
      return minutes * 60 * 1000
    }
    
    if (parts.length > 2 && parts[2].startsWith('*/')) {
      const hours = parseInt(parts[2].substr(2))
      return hours * 60 * 60 * 1000
    }
    
    if (parts[0] === '0' && parts[1] === '0' && parts[2] === '1' && parts[3] === '1' && parts[4] === '1') {
      const now = new Date()
      const nextYear = new Date(now.getFullYear() + 1, 0, 1, 1, 0, 0)
      return nextYear.getTime() - now.getTime()
    }
    
    return null
  }
  
  async runTask(name) {
    const task = this.tasks.get(name)
    if (!task) return
    
    const startTime = Date.now()
    task.stats.lastRun = startTime
    task.stats.runs++
    
    console.log(`⏱️ Running task: ${name}`)
    
    try {
      const result = await task.handler()
      task.stats.success++
      task.stats.lastError = null
      
      console.log(`✅ Task completed: ${name} (${Date.now() - startTime}ms)`)
      
      return result
    } catch (err) {
      task.stats.failed++
      task.stats.lastError = err.message
      console.error(`❌ Task failed: ${name}`, err.message)
      throw err
    } finally {
      const interval = this.parseCron(task.cron)
      if (interval) {
        task.stats.nextRun = Date.now() + interval
      }
    }
  }
  
  getTasks() {
    return _(Array.from(this.tasks.values()))
      .map(task => ({
        name: task.name,
        cron: task.cron,
        ...task.stats
      }))
      .value()
  }
  
  getTask(name) {
    const task = this.tasks.get(name)
    if (!task) return null
    
    return {
      name: task.name,
      cron: task.cron,
      ...task.stats
    }
  }
  
  async triggerTask(name) {
    const task = this.tasks.get(name)
    if (!task) {
      throw new Error(`Task not found: ${name}`)
    }
    
    return await this.runTask(name)
  }
  
  stopTask(name) {
    const timer = this.timers.get(name)
    if (timer) {
      clearInterval(timer)
      this.timers.delete(name)
    }
  }
  
  stop() {
    this.timers.forEach(timer => clearInterval(timer))
    this.timers.clear()
  }
  
  restart(name) {
    this.stopTask(name)
    
    const task = this.tasks.get(name)
    if (task && task.cron) {
      const interval = this.parseCron(task.cron)
      if (interval) {
        const timer = setInterval(() => this.runTask(name), interval)
        this.timers.set(name, timer)
        task.stats.nextRun = Date.now() + interval
      }
    }
  }
}